
#ifndef vhal_CarProperties_H_
#define vhal_CarProperties_H_

#include <Properties.h>
#include <sys/cdefs.h>

#include <limits>
#include <string>

namespace vhal {

class CarProperties {
  public:
    // Returns the current value of the car property `key`,
    // or `default_value` if the property is empty or doesn't exist.
    std::string GetProperty(const std::string& key, const std::string& default_value);

    // Returns true if the car property `key` has the value "1", "y", "yes", "on", or "true",
    // false for "0", "n", "no", "off", or "false", or `default_value` otherwise.
    bool GetBoolProperty(const std::string& key, bool default_value);

    // Returns the signed integer corresponding to the car property `key`.
    // If the property is empty, doesn't exist, doesn't have an integer value, or is outside
    // the optional bounds, returns `default_value`.
    template <typename T>
    T GetIntProperty(const std::string& key, T default_value, T min = std::numeric_limits<T>::min(),
                     T max = std::numeric_limits<T>::max());

    // Returns the unsigned integer corresponding to the car property `key`.
    // If the property is empty, doesn't exist, doesn't have an integer value, or is outside
    // the optional bound, returns `default_value`.
    template <typename T>
    T GetUintProperty(const std::string& key, T default_value,
                      T max = std::numeric_limits<T>::max());

    // Returns the double corresponding to the car property `key`.
    // If the property is empty, doesn't exist, doesn't have an double value, or is outside
    // the optional bound, returns `default_value`.
    double GetDoubleProperty(const std::string& key, double default_value,
                             double min = std::numeric_limits<double>::lowest(),
                             double max = std::numeric_limits<double>::max());

    // Sets the car property `key` to `value`.
    // Note that car property setting is inherently asynchronous so a return value of `true`
    // isn't particularly meaningful, and immediately reading back the value won't necessarily
    // tell you whether or not your call succeeded. A `false` return value definitely means failure.
    bool SetProperty(const std::string& key, const std::string& value);

    // Sets the car property `key` to bool `value`.
    bool SetBoolProperty(const std::string& key, bool value);

    // Sets the car property `key` to signed integer `value`.
    template <typename T>
    bool SetIntProperty(const std::string& key, T value);

    // Sets the car property `key` to unsigned integer `value`.
    template <typename T>
    bool SetUintProperty(const std::string& key, T value);

    // Sets the car property `key` to double `value`.
    bool SetDoubleProperty(const std::string& key, double value);

  protected:
    cppproperties::Properties mProperties;

};  // class CarProperties

}  // namespace vhal

#endif  // vhal_CarProperties_H_
